<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <p>
    <a href="https://blog.csdn.net/lszyzs/article/details/107103603">转载：原文链接</a>
  </p>

<script type="text/javascript">
var arr = ['a', 'b', 'c', 'd', 'e', 10]
Array.prototype.myForeach = function (fn) {
  //    如果不是函数 抛错
  if (typeof fn != 'function') {
    throw new Error(`${fn} is no a function`)
  }
  // this表示当前被调用的数组
  var self = this
  for (var i = 0; i < self.length; i++) {
    fn(self[i], i, self)
  }
}
// arr.myForeach((item, index) => {
//  console.log(item, index)
//  return (arr[index] = index)
// })
// console.log(arr)

// map : 映射，遍历数组并且返回一个新的数组
Array.prototype.myMap = function (fn) {
  // 如果不是函数 抛错
  if (typeof fn != 'function') {
    return new Error(`${fn} is no a function`)
  }
  var self = this
  var selfArray = []
  for (var i = 0; i < self.length; i++) {
    // 调用返回的每一项都放到新数组中
    selfArray[i] = fn(self[i], i, self)
  }
  // 返回新数组
  return selfArray
}
// let newArray = arr.myMap((ite, index, arr) => {
//  return index
// })
// console.log(newArray)

// filter: 返回满足条件的每一项到新数组
Array.prototype.myFilter = function (fn) {
  if (typeof fn != 'function') {
    return new Error(`${fn} is no a function`)
  }
  let self = this
  let newArray = []
  for (var i = 0; i < self.length; i++) {
    // if (fn(self[i], i, self)) {
    //  newArray.push(self[i])
    // }
    // 调用fn函数返回结果，如果满足条件则把此项放入新数组中
    fn(self[i], i, self) && newArray.push(self[i])
  }
  return newArray
}
// let filterArray = arr.myFilter((item) => {
//  return item == 'a'
// })
// console.log(filterArray)

// find: 返回满足条件的第一个元素
Array.prototype.myFind = function (fn) {
  if (typeof fn != 'function') {
    return new Error(`${fn} is no a function`)
  }
  let self = this
  for (var i = 0; i < self.length; i++) {
    if (fn(self[i], i, self)) {
      // 如果当前元素满足，则返回此元素
      return self[i]
    }
  }
}
// let findArray = arr.myFind((ite) => {
//  return ite > 9
// })
// console.log(findArray)
/*if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    value:function(fn) {
    //https://blog.csdn.net/lszyzs/article/details/107103603
    //https://segmentfault.com/q/1010000009419821  1 >>> 0
    
    // 1. Let O be ? ToObject(this value).
    if (this == null) {
      throw new TypeError('"this" is null or not defined')
    }

    var o = Object(this);

    // 2. Let len be ? ToLength(? Get(O, "length")).
    var len = o.length >>> 0;
    
    // 3. If IsCallable(fn) is false, throw a TypeError exception.
    if (typeof fn !== 'function') {
      throw new TypeError('fn must be a function');
    }

    // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
    var thisArg = arguments[1];

    // 5. Let k be 0
    var k = 0;
    console.log(arguments[1])

    // 6. Repeat, while k < len
    while(k < len) {
      // a. Let Pk be ! ToString(k).
      // b. Let kValue be ? Get(O, Pk).
      // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
      // d. If testResult is true, return kValue.
      var kValue = o[k];
      if (fn.call(thisArg, kValue, k, o)) {
        return kValue
      }
      // e. Increase k by 1.
      k++
    }

    // 7. Return undefined.
    return undefined
  }
}*/

// every: 判断数组中每一项是否满足条件 如有是返回true 否则返回false
Array.prototype.myEvery = function (fn) {
  if (typeof fn != 'function') {
    return new Error(`${fn} is no a function`)
  }
  let self = this
  for (var i = 0; i < self.length; i++) {
    // 如果数组中有一项不满足条件，则返回false
    if (!fn(self[i], i, self)) {
      return false
    }
  }
  // 否则返回true（循环遍历已经完成，没有为false的）
  return true
}
// let isEvery = arr.myEvery((ite) => {
//  return ite > 9
// })
// console.log(isEvery)

// some: 判断数组中是否有一项满足条件，如果有返回true，否则返回false
Array.prototype.mySome = function (fn) {
  if (typeof fn != 'function') {
    return new Error(`${fn} is no a function`)
  }
  let self = this
  for (var i = 0; i < self.length; i++) {
    //当前项如果满足条件则返回true
    if (fn(self[i], i, self)) {
      return true
    }
  }
  // 循环遍历已经完成，依然没有一项为true，则返回false
  return false
}
// let isSome = arr.mySome((ite) => {
//  return ite > 9
// })
// console.log(isSome)
</script>
</body>
</html>